package de.hauschild.gmltracer.tracer.impl;

import java.util.List;

import org.apache.commons.math.geometry.Vector3D;

import de.hauschild.gmltracer.tracer.Intersection;
import de.hauschild.gmltracer.tracer.Light;
import de.hauschild.gmltracer.tracer.Ray;
import de.hauschild.gmltracer.tracer.Shape;
import de.hauschild.gmltracer.tracer.SurfaceProperties;

/**
 * A simple extension of {@link AbstractRayRenderer} implementing the Phong illumination model by solving the following
 * equation. <code>I = kd*Ia*C + kd*SUM((N.Lj)*Ij*C) + ks*SUM(((N.Hj)^n)*Ij*C) + Ks*Is*C</code> where
 * <ul>
 * <li>TODO</li>
 * </ul>
 * 
 * @since 1.0.0
 * @author Klaus Hauschild
 */
public class SimpleRayRenderer extends AbstractRayRenderer {

  @Override
  protected Vector3D renderRayRecursive(final Ray ray, final Shape scene, final Vector3D ambientLightIntensity,
      final List<Light> lights, final int tracingDepth, final int currentTracingDepth) {
    // test for intersection
    final Intersection intersection = scene.intersect(ray);
    // there was a intersection
    if (intersection != null) {
      // get the surface properties
      final SurfaceProperties surfaceProperties = scene.getSurfaceProperties(intersection.getPoint());
      // ambient color
      final Vector3D ambientColor = Vector3DUtils.multiplyComponentwise(surfaceProperties.getColor(),
          ambientLightIntensity).scalarMultiply(surfaceProperties.getDiffuseReflectionCoefficient());
      // light color
      Vector3D lightColor = Vector3D.zero;
      for (final Light light : lights) {
        if (!light.isInShadow(scene, intersection)) {
          final Vector3D currentLightColor = light.illuminates(surfaceProperties.getColor(), intersection);
          lightColor = lightColor.add(currentLightColor);
        }
      }
      lightColor = lightColor.scalarMultiply(surfaceProperties.getDiffuseReflectionCoefficient());
      // specular color for reflected ray
      final Ray reflectedRay = Vector3DUtils.reflectRay(ray, intersection.getNormal());
      Vector3D specularColor = renderRay(reflectedRay, scene, ambientLightIntensity, lights, tracingDepth,
          currentTracingDepth + 1);
      specularColor = Vector3DUtils.multiplyComponentwise(specularColor, surfaceProperties.getColor()).scalarMultiply(
          surfaceProperties.getSpecularReflectionCoefficient());
      // XXX remove me
      specularColor = Vector3D.zero;
      // XXX remove me
      // compute color
      return ambientColor.add(lightColor).add(specularColor);
    }
    return Vector3D.zero;
  }

}
